home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / X-Ray / samples / transparent floater / source / floater.c < prev    next >
Encoding:
Text File  |  1999-06-09  |  5.3 KB  |  192 lines  |  [TEXT/CWIE]

  1. // Copyright (C) 1999 Eric Roccasecca.  All rights reserved.
  2.  
  3. #include <TextServices.h>
  4. #include <AppleEvents.h>
  5.  
  6. #include "common.h"
  7. #include "X_Ray.h"
  8.  
  9.  
  10. enum {
  11.     kNewWindowProcInfo = kPascalStackBased
  12.         | RESULT_SIZE (SIZE_CODE(sizeof(WindowPtr)))
  13.         | STACK_ROUTINE_PARAMETER(1,SIZE_CODE(sizeof(void*)))
  14.         | STACK_ROUTINE_PARAMETER(2,SIZE_CODE(sizeof(Rect*)))
  15.         | STACK_ROUTINE_PARAMETER(3,SIZE_CODE(sizeof(char*)))
  16.         | STACK_ROUTINE_PARAMETER(4,SIZE_CODE(sizeof(Boolean)))
  17.         | STACK_ROUTINE_PARAMETER(5,SIZE_CODE(sizeof(short)))
  18.         | STACK_ROUTINE_PARAMETER(6,SIZE_CODE(sizeof(WindowPtr)))
  19.         | STACK_ROUTINE_PARAMETER(7,SIZE_CODE(sizeof(Boolean)))
  20.         | STACK_ROUTINE_PARAMETER(8,SIZE_CODE(sizeof(long)))
  21. };
  22.  
  23. /* Globals */
  24. Rect                gWinRect;
  25. WindowPtr            gWin;
  26. WindowRecord        gWinRec;
  27. Boolean                gDone = false;
  28. OSErr                gErr;
  29. AEEventHandlerUPP    gQuitHandlerUPP;
  30. PicHandle            gWinPic;
  31. flt_GlobalCommPtr    gCommRec = nil;
  32.  
  33. UniversalProcPtr    gOldNewWindowPtr, gNewWindowUPP;
  34. Boolean                gMakingFloaters = false;
  35.  
  36. /* Prototypes */
  37. void HandleEvent (EventRecord *theEvent);
  38. pascal OSErr MyQuitHandler (const AppleEvent *theAppleEvent, const AppleEvent * reply, long handlerRefcon);
  39. Boolean PrepForMakingWindows (void);
  40. pascal WindowPtr flt_NewWindow (void *wStorage, const Rect *boundsRect, ConstStr255Param title, Boolean visible, short theProc, WindowPtr behind, Boolean goAwayFlag, long refCon);
  41. void AppCodeFragmentDied (void);
  42.  
  43.  
  44. void main (void)
  45. {
  46.     EventRecord        theEvent;
  47.     
  48.     InitGraf (&qd.thePort);
  49.     
  50.     gWinPic = GetPicture (128);
  51.     if (gWinPic == nil)
  52.         ExitToShell();
  53.     
  54.     PrepForMakingWindows();
  55.         
  56.     // use the picture's rectangle for the window size
  57.     gWinRect = (*gWinPic)->picFrame;
  58.     SetRect (&gWinRect, 0, 0, gWinRect.right - gWinRect.left, gWinRect.bottom - gWinRect.top);
  59.     OffsetRect (&gWinRect, 50, 50);
  60.     
  61.     gMakingFloaters = true;
  62.     gErr = NewTransparentServiceWindow (&gWinRec, &gWinRect, "\p", true, kWindowFloatProc, (WindowPtr) -1, true, (ComponentInstance)kSystemProcess, &gWin, nil, nil);
  63.     gMakingFloaters = false;
  64.     if (gErr != noErr)
  65.         ExitToShell();
  66.     
  67.     HiliteWindow (gWin, true);
  68.     SetPort (gWin);    
  69.     EraseRect (&gWin->portRect);
  70.     DrawPicture (gWinPic, &gWin->portRect);
  71.         
  72.     gErr = Gestalt (kfltGestalt, (long*)&gCommRec);
  73.     if (gErr == noErr)
  74.     {
  75.         gErr = GetCurrentProcess (&gCommRec->daemonPSN);
  76.         gCommRec->daemonWindow = gWin;
  77.         gCommRec->daemonZone = GetZone();
  78.         gCommRec->daemonQDGlobals = &qd;
  79.         gCommRec->daemonCloseWindow = false;
  80.     }
  81.     else
  82.         ExitToShell();
  83.     
  84.     gQuitHandlerUPP = NewAEEventHandlerProc (MyQuitHandler);
  85.     gErr = AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, gQuitHandlerUPP, false, false);
  86.     
  87.     while (!gDone)
  88.     {
  89.         WaitNextEvent (everyEvent, &theEvent, 60, nil);
  90.         HandleEvent (&theEvent);
  91.     }
  92.     
  93.     if (gWin)
  94.     {
  95.         gErr = CloseTransparentServiceWindow (gWin);
  96.         gWin = nil;
  97.     }
  98.     
  99.     if (gCommRec)
  100.     {
  101.         gCommRec->daemonPSN.lowLongOfPSN = 0;
  102.         gCommRec->daemonPSN.highLongOfPSN = 0;
  103.         gCommRec->daemonWindow = nil;
  104.         gCommRec->daemonZone = 0;
  105.         gCommRec->daemonQDGlobals = nil;
  106.         
  107.         gCommRec = nil;
  108.     }
  109. }
  110.  
  111.  
  112. void HandleEvent (EventRecord *theEvent)
  113. {
  114.     if (theEvent->what == nullEvent)
  115.     {
  116.         if (gCommRec)
  117.         {
  118.             // see if we were signaled to quit
  119.             if (gCommRec->daemonCloseWindow)
  120.             {
  121.                 gDone = true;
  122.                 gCommRec->daemonCloseWindow = false; // reset this
  123.             }
  124.         }
  125.         
  126.         // a handy way to service update events in text service floating windows
  127.         if (!EmptyRgn (((WindowPeek)gWin)->updateRgn))
  128.         {
  129.             DrawPicture (gWinPic, &gWin->portRect);
  130.             SetEmptyRgn (((WindowPeek)gWin)->updateRgn);
  131.         }
  132.     }
  133.     else if (theEvent->what == kHighLevelEvent)
  134.         gErr = AEProcessAppleEvent (theEvent);
  135. }
  136.  
  137.  
  138. pascal OSErr MyQuitHandler (const AppleEvent* theAppleEvent, const AppleEvent* reply, long handlerRefcon)
  139. {
  140. #pragma unused (theAppleEvent, reply, handlerRefcon)
  141.     gDone = true;
  142.     return noErr;
  143. }
  144.  
  145.  
  146. // applies a patch to NewWindow so TSM windows can be colorized
  147. // this is useful for pre Mac OS 8.5 systems
  148. // 8.5 or higher there is finally a system call for color text service windows
  149. Boolean PrepForMakingWindows (void)
  150. {
  151.     // Apply local patch to NewWindow
  152.     gOldNewWindowPtr = NGetTrapAddress (_NewWindow, ToolTrap);
  153.     gNewWindowUPP = NewRoutineDescriptor ((ProcPtr)flt_NewWindow, kNewWindowProcInfo, GetCurrentArchitecture());
  154.     if (!gNewWindowUPP)
  155.         return false;
  156.     NSetTrapAddress (gNewWindowUPP, _NewWindow, ToolTrap);
  157.     return true;
  158. }
  159.  
  160.  
  161. // fakes out text services maanger and returns a color window instead of black and white window
  162. pascal WindowPtr flt_NewWindow (void *wStorage, const Rect *boundsRect, ConstStr255Param title, Boolean visible, short theProc, WindowPtr behind, Boolean goAwayFlag, long refCon)
  163. {
  164.     if (!gMakingFloaters)
  165.         return (WindowPtr)CallUniversalProc (gOldNewWindowPtr, kNewWindowProcInfo, wStorage, boundsRect, title, visible, theProc, behind, goAwayFlag, refCon);
  166.     else
  167.         return NewCWindow (wStorage, boundsRect, title, visible, theProc, behind, goAwayFlag, refCon);
  168. }
  169.  
  170.  
  171. // used when the code fragment that contains this app goes away
  172. // to make sure it cleans up after itself
  173. // this is best used in cases of crashes or being unable to fully intialize
  174. void AppCodeFragmentDied (void)
  175. {
  176.     if (gWin)
  177.     {
  178.         gErr = CloseTransparentServiceWindow (gWin);
  179.         gWin = nil;
  180.     }
  181.     
  182.     if (gCommRec)
  183.     {
  184.         gCommRec->daemonPSN.lowLongOfPSN = 0;
  185.         gCommRec->daemonPSN.highLongOfPSN = 0;
  186.         gCommRec->daemonWindow = nil;
  187.         gCommRec->daemonZone = 0;
  188.         gCommRec->daemonQDGlobals = nil;
  189.         
  190.         gCommRec = nil;
  191.     }
  192. }